#ifndef CIVIEW_SCENE_H
#define CIVIEW_SCENE_H

#include "../Core/MaterialLib.h"
#include "../Core/GroupLib.h"
#include "../Geometries/Geometry.h"

namespace CIView {
    /**
     * This class includes all data needed to render the 3D scene     
     **/
    class Scene {
        //Friend classes
        friend class View;

    public:
        Scene();                //Constructor
        virtual ~Scene();       //Destructor

    protected:
        std::map<const char*, CIGeom::Geometry*> geometries;        //The scene's geometries
        unsigned int geometriesCounter;                             //The number of geometries that have been added to the scene

        CICore::MaterialLib matLib;                                 //The materials library
        CICore::GroupLib groupLib;                                  //The groups library

        unsigned int selectionMode;                                 //The current selection mode in the scene

    public:
        //Utility methods
        bool AddGeometry (CIGeom::Geometry* g);                     //Method called to add a geometry in the scene
        void RemoveGeometry (const char* geometryName);             //Method called to remove a geometry from the scene
        CIGeom::Geometry* GetGeometry (const char* geometryName);   //Method called to get a geometry present in the scene
        std::map<const char*, CIGeom::Geometry*>& GetGeometries();  //Method called to get a reference to the scene's geometries

        unsigned int GenerateNewGeometryID();               //Method called to get a reference to the number of geometries that have been added to the scene (used to set the geometries name)                

        void Render();                                      //Method called to render the entire scene

        void SelectAllVertices();                           //Method called to select all scene's geometries vertices
        void DeselectAllVertices();                         //Method called to deselect all scene's geometries vertices
        void InvertVerticesSelection();                     //Method called to invert the current vertices selection status        
        
        void SelectAllFaces();                              //Method called to select all scene's geometries faces
        void DeselectAllFaces();                            //Method called to deselect all scene's geometries faces
        void InvertFacesSelection();                        //Method called to invert the current faces selection status        

        void HideSelectedVertices();                        //Method called to hide the selected vertices
        void HideSelectedFaces();                           //Method called to hide the selected faces
        void UnhideAll();                                   //Method called to unhide all the primitives

        bool HasHiddenPrimitives();                         //Method called to know if there are hidden primitives in the scene

        void LoadGeometriesNames();                         //Method called to load the names that identify the geometries in the OpenGL names stack               
        void LoadFacesNames();                              //Method called to load the names for the geometries faces in the OpenGL names stack       
        void LoadVerticesNames();                           //Method called to load the names for the geometries vertices in the OpenGL names stack       
        //unsigned int GetNumberOfFaces();                    //Method called to get the total number of faces of the scene geometries
        //std::vector<CICore::Face*>* GetAllFaces();          //Method called to get an array that contains pointers to all faces in the scene


        void ApplyMatrix (const CICore::Matrix& m);         //Method called to apply a matrix transformation to the selected vertices in the scene

        unsigned int GetSelectionMode();                    //Method called to get the current selection mode enabled
        void SetSelectionMode (unsigned int mode);          //Method called to set the current selection mode enabled

        //virtual bool LoadFromCI3D (QIODevice* device);

        //virtual void SaveAsCI3D (const char* filename);
        
        //Boolean to indicate if the current scene has been saved or not
        bool saved;
    };
}

#endif /* CIVIEW_SCENE_H */
